<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>大屏渲染</title>
    <link rel="stylesheet" href="./index.css">

    <script type="importmap">
    {
        "imports": {
        "three": "../three/v170/three.module.min.js",
        "three/addons/": "../three/v170/"
        }
    }
    </script>
</head>

<body>

    <div class="screen-wrapper">
        <!-- 中间threejs的渲染区域 -->
        <div class="three-box" id="three-box"></div>

        <!-- 顶部标题区域 -->
        <div class="screen-top-area">
            <div class="top-title">蓝色可视化大屏大标题</div>
        </div>

        <!-- 左侧图表容器 -->
        <div class="chart-left-wrapper">
            <div class="chart-block">
                <div class="chart-title">左侧第一个图形</div>
                <div class="chart-content">
                    <!-- <img src="./images/side_01.png" /> -->
                    <div id="chart_left_01" class="chart-box"></div>
                </div>
            </div>

            <div class="chart-block">
                <div class="chart-title">左侧第二个图形</div>
                <div class="chart-content">
                    <!-- <img src="./images/side_03.png" /> -->
                    <div id="chart_left_02" class="chart-box"></div>
                </div>
            </div>

            <div class="chart-block">
                <div class="chart-title">左侧第三个图形</div>
                <div class="chart-content">
                    <!-- <img src="./images/side_05.png" /> -->
                    <div id="chart_left_03" class="chart-box"></div>
                </div>
            </div>
        </div>

        <!-- 右侧图表容器 -->
        <div class="chart-right-wrapper">
            <div class="chart-block">
                <div class="chart-title">右侧第一个图形</div>
                <div class="chart-content">
                    <!-- <img src="./images/side_02.png" /> -->
                    <div id="chart_right_01" class="chart-box"></div>
                </div>
            </div>

            <div class="chart-block">
                <div class="chart-title">右侧第二个图形</div>
                <div class="chart-content">
                    <!-- <img src="./images/side_03.png" /> -->
                    <div id="chart_right_02" class="chart-box"></div>
                </div>
            </div>

            <div class="chart-block">
                <div class="chart-title">右侧第三个图形</div>
                <div class="chart-content">
                    <!-- <img src="./images/side_04.png" /> -->
                    <div id="chart_right_03" class="chart-box"></div>
                </div>
            </div>
        </div>
    </div>

    <div id="scene-container"></div>


    <div style="position: fixed;left: 0;top: 0;z-index: 9999;display: none;">
        <button id="x_increase">x_增加</button>
        <button id="x_decrease">x_减少</button>
        <button id="y_increase">y_增加</button>
        <button id="y_decrease">y_减少</button>
    </div>

    <div style="position: fixed;left: 0;top: 0;z-index: 9999;">
        <button id="reset_btn">还原</button>
    </div>

    <script src="../static/js/echarts.min-5.5.1.js"></script>
    <script type="module">
        import * as THREE from 'three';
        import { CSS2DRenderer, CSS2DObject } from "three/addons/renderers/CSS2DRenderer.js";
        import { CSS3DRenderer, CSS3DObject } from "three/addons/renderers/CSS3DRenderer.js";
        import { TrackballControls } from 'three/addons/controls/TrackballControls.js';
        import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
        import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
        import { DragControls } from 'three/addons/controls/DragControls.js';
        import { GUI } from 'three/addons/libs/lil-gui.module.min.js';

        console.log(`[THREE版本]`, THREE.REVISION);

        let scene, camera, renderer, controls, isPaused;
        let labelRenderer = null;
        let middle_shebei = {};// 设备--用于位置
        let middle_dengguang = null;// 灯光--射光灯

        const raycaster = new THREE.Raycaster();
        const mouse = new THREE.Vector2();

        const texturedPlanes = [];

        // 添加纹理的函数
        function addTexturedPlane(obj) {
            const textureLoader = new THREE.TextureLoader();
            const texture = textureLoader.load(obj.imgURL, function (texture) {
                texture.anisotropy = renderer.capabilities.getMaxAnisotropy();
                texture.minFilter = THREE.LinearMipmapLinearFilter;
                texture.magFilter = THREE.LinearFilter;
                texture.generateMipmaps = true;
                texture.wrapS = texture.wrapT = THREE.ClampToEdgeWrapping;

                // texture.minFilter = THREE.LinearFilter; // 尝试使用线性过滤
                texture.magFilter = THREE.LinearFilter; // 同样使用线性过滤

                const cur_widht = obj.width;
                const cur_height = obj.height;
                const cur_xishu = 0.02;// 缩小的系数
                // const cur_xishu = 0.0185;// 缩小的系数
                const geometry = new THREE.PlaneGeometry(cur_widht * cur_xishu, cur_height * cur_xishu); // 根据图片比例设置平面尺寸

                const material = new THREE.MeshBasicMaterial({
                    map: texture,
                    transparent: true, // 允许透明
                    opacity: 1, // 设置不透明度（0.0为完全透明，1.0为完全不透明）
                    side: THREE.DoubleSide, // 设置材质为双面
                    blending: THREE.NormalBlending, // 使用正常混合模式
                    // depthTest: false, // 禁用深度测试
                    // depthWrite: false // 禁止写入深度缓冲
                    // metalness: 0, // 设置金属度为 0.5
                    // alphaTest: 0.1,// 透明度阈值
                    // color: 0xffffff, // 设置材质颜色
                });
                material.map.colorSpace = THREE.SRGBColorSpace;

                const plane = new THREE.Mesh(geometry, material);
                plane.material.depthWrite = false;// 该平面在渲染时会写入深度缓冲区

                plane.position.set(obj.x, obj.y, obj.z);
                plane.renderOrder = obj.renderOrder || 0; // 设置渲染顺序

                scene.add(plane);

                if (obj.labelObj) {
                    if (obj.labelObj.type === 'machine_1') {
                        createLabel(plane, { ...obj.labelObj });
                        middle_shebei[obj.labelObj.name] = plane;
                    } else if (obj.labelObj.type === 'machine_2') {
                        createLabel(plane, { ...obj.labelObj });
                        middle_shebei[obj.labelObj.name] = plane;
                    }
                }
            });
        }

        function updateLabelPosition(label, newPosition) {
            label.position.set(newPosition[0], newPosition[1], newPosition[2]);
        }
        const newPosition = [1, 2, 3]; // 新的x, y, z位置

        function createLabel(object, data) {
            object.geometry.computeBoundingBox(); // 计算包围盒

            const labelDiv = document.createElement('div');
            labelDiv.className = 'label-wrapper';
            labelDiv.innerHTML = `
        <div class="label-bottom"></div>
        <div class="label-line-1"></div>
        <div class="label-line-2"></div>
        <div class="label-content">
            <h3 class="label-name">${data.name}</h3>
            <div class="label-item">进程:xxxx</div>
            <div class="label-item">进程:xxxx</div>
            <div class="label-item">进程:xxxx</div>
            <div class="label-item">进程:xxxx</div>
        </div>
    `;

            // Change from CSS2DObject to CSS3DObject
            const label = new CSS2DObject(labelDiv);

            const p_x = (data.position || [])[0] || 0;
            const p_y = (data.position || [])[1] || object.geometry.boundingBox.max.y || 0;
            const p_z = (data.position || [])[2] || 0;

            if (data.position) {
                console.log(`bigScreen.html 201 [data.position]`, data.position);
            }

            label.position.set(p_x, p_y, p_z);

            middle_shebei[data.name + '_xuanfu'] = label;
            console.log(`bigScreen.html 209 [middle_shebei['2号机台'].position]`, middle_shebei[data.name + '_xuanfu'].position);

            object.add(label);
        }

        function init() {
            scene = new THREE.Scene();
            camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
            camera.rotation.set(0, 0, 0);
            // camera.position.set(10, 10, 10);
            camera.position.set(0, 0, 15);// 正视图
            // camera.lookAt(new THREE.Vector3(0, 0, 0));

            // 创建渲染器
            renderer = new THREE.WebGLRenderer({
                antialias: true,//
                alpha: true,// 设置背景透明
                physicallyCorrectLights: true,// 开启物理光照
                logarithmicDepthBuffer: true,// 开启深度缓存
                powerPreference: "high-performance",// 
            });
            renderer.setSize(window.innerWidth, window.innerHeight);
            renderer.setPixelRatio(window.devicePixelRatio);
            document.getElementById('three-box').appendChild(renderer.domElement);

            labelRenderer = new CSS2DRenderer();
            labelRenderer.setSize(window.innerWidth, window.innerHeight);
            labelRenderer.domElement.style.position = 'absolute';
            // 不遮挡canvas和threejs的点击事件;导致使用CSS2DObject添加的HTML标签点击事件无效;
            labelRenderer.domElement.style.pointerEvents = 'none';
            labelRenderer.domElement.style.top = '0';
            document.getElementById('scene-container').appendChild(labelRenderer.domElement);

            // 创建坐标轴辅助对象
            // var axesHelper = new THREE.AxesHelper(1000);
            // scene.add(axesHelper);

            // 添加控制器
            controls = new OrbitControls(camera, renderer.domElement);
            // 添加平移功能
            controls.enablePan = true;

            // 添加环境光
            const ambientLight = new THREE.AmbientLight(0xffffff, 1);
            scene.add(ambientLight);

            // 添加平行光
            const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
            directionalLight.position.set(15, 15, 0);// 设置光源位置
            scene.add(directionalLight);

            // 窗口调整
            window.addEventListener('resize', () => {
                camera.aspect = window.innerWidth / window.innerHeight;
                camera.updateProjectionMatrix();
                renderer.setSize(window.innerWidth, window.innerHeight);
                labelRenderer.setSize(window.innerWidth, window.innerHeight);
            });

            window.addEventListener('click', onMouseClick, false);

            // 添加键盘事件监听器
            document.addEventListener('keydown', function (event) {
                // 向上平移
                if (event.keyCode === 38) {
                    controls.pan(new THREE.Vector3(0, 1, 0));
                }
                // 向下平移
                else if (event.keyCode === 40) {
                    controls.pan(new THREE.Vector3(0, -1, 0));
                }
            });

            loop();

            // 添加场景背景图
            addTexturedPlane({
                imgURL: './images/souce_05.png',
                width: 1393,
                height: 972,
                x: 0,
                y: 0,
                z: 0,
                renderOrder: 1, // 设置渲染顺序
            })
            // 添加流水线
            addTexturedPlane({
                imgURL: './images/souce_02.png',
                width: 715,
                height: 644,
                x: -0.799999,
                y: -1.3,
                z: 0,
                renderOrder: 2, // 设置渲染顺序
            })
            // 添加设备 1-1
            addTexturedPlane({
                imgURL: './images/souce_01.png',
                width: 107,
                height: 96,
                x: -10.7,
                y: -2.4,
                z: 0,
                renderOrder: 3, // 设置渲染顺序
                labelObj: {
                    type: 'machine_1',
                    name: '1号机台',
                    position: [0.04999999999999999, 0.6934999823570249, 0],// 悬浮窗位置信息
                },
            })
            // 添加设备 1-2
            addTexturedPlane({
                imgURL: './images/souce_01.png',
                width: 107,
                height: 96,
                x: -8.8,
                y: -3.4,
                z: 0,
                renderOrder: 4, // 设置渲染顺序
                labelObj: {
                    type: 'machine_1',
                    name: '2号机台',
                    position: [0.04999999999999999, 0.6934999823570249, 0],// 悬浮窗位置信息
                },
            })
            // 添加设备 2-1
            addTexturedPlane({
                imgURL: './images/souce_03.png',
                width: 111,
                height: 102,
                x: -3.6,
                y: -6.49,
                z: 0,
                renderOrder: 5, // 设置渲染顺序
                labelObj: {
                    type: 'machine_2',
                    name: '3号机台',
                    position: [-0.35, 0.24349998235702486, 0],// 悬浮窗位置信息
                },
            })
            // 添加设备 2-2
            addTexturedPlane({
                imgURL: './images/souce_03.png',
                width: 111,
                height: 102,
                x: 0.908999,
                y: -2.3,
                z: 0,
                renderOrder: 6, // 设置渲染顺序
                labelObj: {
                    type: 'machine_2',
                    name: '4号机台',
                    position: [-0.35, 0.24349998235702486, 0],// 悬浮窗位置信息
                },
            })
            // 添加设备 2-3
            addTexturedPlane({
                imgURL: './images/souce_03.png',
                width: 111,
                height: 102,
                x: -1.199999,
                y: -0.01222,
                z: 0,
                renderOrder: 7, // 设置渲染顺序
                labelObj: {
                    type: 'machine_2',
                    name: '5号机台',
                    position: [-0.35, 0.24349998235702486, 0],// 悬浮窗位置信息
                },
            })
            // 添加设备 2-4
            addTexturedPlane({
                imgURL: './images/souce_03.png',
                width: 111,
                height: 102,
                x: 1.95999,
                y: 1.59999,
                z: 0,
                renderOrder: 8, // 设置渲染顺序
                labelObj: {
                    type: 'machine_2',
                    name: '6号机台',
                    position: [-0.35, 0.2434999, 0],// 悬浮窗位置信息
                },
            })
            // 添加设备 2-5
            addTexturedPlane({
                imgURL: './images/souce_03.png',
                width: 111,
                height: 102,
                x: 6.2999,
                y: -0.2000999,
                z: 0,
                renderOrder: 9, // 设置渲染顺序
                labelObj: {
                    type: 'machine_2',
                    name: '7号机台',
                    position: [-0.3999999, 0.2434999, 0],// 悬浮窗位置信息
                },
            })
            // 添加 设备2-6
            addTexturedPlane({
                imgURL: './images/souce_03.png',
                width: 111,
                height: 102,
                x: 8.4998,
                y: -1.400099,
                z: 0,
                renderOrder: 10, // 设置渲染顺序
                labelObj: {
                    type: 'machine_2',
                    name: '8号机台',
                    position: [0.5, 0.743499, 0],// 悬浮窗位置信息
                },
            })

            setTimeout(() => {
                addGUI();// 添加GUI
            }, 1000)
        }

        function addGUI() {
            // 创建 GUI，设置gui面板的标题
            // const gui = new GUI({ 'title': "操作区" });
            // const obj = {
            //     color: '#ff0000',
            //     speed: 2.5,
            //     isVisible: true,
            //     selectedOptions: ['苹果🍎']
            // };

            // gui.addColor(obj, 'color').onChange((value) => {
            //     sphereMa.color.set(value);
            // });

            // const sphereFol = gui.addFolder('机台位置');
            // console.log(`bigScreen.html 410 [middle_shebei['1号机台']]`, middle_shebei['1号机台']);
            // sphereFol.add(middle_shebei['2号机台'].position, 'x', -20, 20, 0.1)
            // sphereFol.add(middle_shebei['2号机台'].position, 'y', -20, 20, 0.1)

            // const sphereFol_2 = gui.addFolder('悬浮窗');
            // sphereFol_2.add(middle_shebei['2号机台'].position, 'x', -20, 20, 0.1).onChange(function (value) {
            //     updateLabelPosition(middle_shebei['2号机台'], [value, middle_shebei['2号机台'].position.y, middle_shebei['2号机台'].position.z]);
            // });
            // sphereFol_2.add(middle_shebei['2号机台'].position, 'y', -20, 20, 0.1).onChange(function (value) {
            //     updateLabelPosition(middle_shebei['2号机台'], [middle_shebei['2号机台'].position.x, value, middle_shebei['2号机台'].position.z]);
            // });


            // const cameraFol = gui.addFolder('相机')
            // cameraFol.add(camera.position, 'x', -5, 8, 0.1)
            // cameraFol.add(camera.position, 'y', -5, 8, 0.1)
            // cameraFol.add(camera.position, 'z', -5, 8, 0.1)

            // const lightFol = gui.addFolder('灯光')
            // lightFol.add(light.position, 'x', -5, 5, 0.1)
            // lightFol.add(light.position, 'y', -5, 5, 0.1)
            // lightFol.add(light.position, 'z', -5, 5, 0.1)
        }

        function onMouseClick(event) {
            // 将鼠标位置转换为归一化设备坐标 (-1 到 +1)
            mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
            mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;

            // 更新射线
            raycaster.setFromCamera(mouse, camera);

            // 检测射线与场景中的对象相交
            const intersects = raycaster.intersectObjects(scene.children);

            // 如果有相交的对象
            if (intersects.length > 0) {
                const intersectedPoint = intersects[0].point; // 获取交点
                console.log('x:', intersectedPoint.x.toFixed(2)); // 输出相对坐标
                console.log('y:', intersectedPoint.y.toFixed(2)); // 输出相对坐标
            }
        }

        var skip;
        function loop() {
            skip++;
            requestAnimationFrame(loop);
            if (skip < 1) {
                return;
            } else {
                skip = 0;
            }

            controls.update(); // 更新控制器
            renderer.render(scene, camera); // 渲染场景
            labelRenderer.render(scene, camera); // 渲染标签
        }

        init();

        // 获取按钮元素
        const x_increase = document.getElementById('x_increase');
        const x_decrease = document.getElementById('x_decrease');
        const y_increase = document.getElementById('y_increase');
        const y_decrease = document.getElementById('y_decrease');

        const cur_jitai = '1号机台';
        const cur_name = cur_jitai + '_xuanfu';
        function con_position() {
            console.log('xy坐标', [middle_shebei[cur_name].position.x, middle_shebei[cur_name].position.y])
        }
        x_increase.addEventListener('click', () => {
            middle_shebei[cur_name].position.x += 0.05;
            con_position()
        });
        x_decrease.addEventListener('click', () => {
            middle_shebei[cur_name].position.x -= 0.05;
            con_position()
        });
        y_increase.addEventListener('click', () => {
            middle_shebei[cur_name].position.y += 0.05;
            con_position()
        });
        y_decrease.addEventListener('click', () => {
            middle_shebei[cur_name].position.y -= 0.05;
            con_position()
        });

        // 还原 初始化的场景
        const reset_btn = document.getElementById('reset_btn');
        reset_btn.addEventListener('click', () => {
            controls.reset();

            controls.update(); // 更新控制器
            renderer.render(scene, camera); // 渲染场景
            labelRenderer.render(scene, camera); // 渲染标签
            console.log(`bigScreen.html 566 ['架子啊玩不']`, '架子啊玩不');
        });
    </script>

    <script src="./chartRender.js"></script>

</body>

</htm>